package com.cnzhy.session;

import com.cnzhy.binding.MyMapperRegistry;
import com.cnzhy.config.Function;
import com.cnzhy.config.MapperStatement;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

/**
 * @author 赵 岩
 */
public class MyConfiguration {

    private static final ClassLoader classLoader = ClassLoader.getSystemClassLoader();

    public Connection build(String resource) throws DocumentException, ClassNotFoundException {
        InputStream stream = classLoader.getResourceAsStream(resource);
        SAXReader reader = new SAXReader();
        Document document = reader.read(stream);
        Element root = document.getRootElement();
        return evalDataSource(root);
    }

    private Connection evalDataSource(Element node) throws ClassNotFoundException {
        if (!"database".equals(node.getName())) {
            throw new RuntimeException("数据文件配置有问题");
        }
        String driverClassName = null;
        String url = null;
        String username = null;
        String password = null;
        for (Object item : node.elements("property")) {
            Element i = (Element) item;
            String value = getValue(i);
            String name = i.attributeValue("name");
            if (name == null || value == null) {
                throw new RuntimeException("数据文件配置有问题");
            }
            if ("driverClassName".equals(name)) {
                driverClassName = value;
            }
            if ("url".equals(name)) {
                url = value;
            }
            if ("username".equals(name)) {
                username = value;
            }
            if ("password".equals(name)) {
                password = value;
            }
        }
        Class.forName(driverClassName);
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(url, username, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;
    }

    private String getValue(Element node) {
        return node.hasContent() ? node.getText() : node.attributeValue("value");
    }

    public void registryMappers(String path) throws UnsupportedEncodingException {
        URL url = this.getClass().getClassLoader().getResource(path);
        for (File file : Objects.requireNonNull(new File(URLDecoder.decode(url.getPath(), "UTF-8")).listFiles())) {
            readMappers(file);
        }
    }

    public void readMappers(File file) {
        if (file.isFile()) {
            readMapper(file);
        }
        if (file.isDirectory()) {
            readMappers(file);
        }
    }

    public MapperStatement readMapper(File file) {
        MapperStatement mapper = new MapperStatement();
        try {
            SAXReader reader = new SAXReader();
            Document document = reader.read(file);
            Element root = document.getRootElement();
            if (root.attributeValue("namespace") == null) {
                throw new RuntimeException("文件配置不对");
            }
            mapper.setInterfaceName(root.attributeValue("namespace").trim());
            List<Function> functionList = new ArrayList<>();
            for (Iterator<?> rootIter = root.elementIterator(); rootIter.hasNext(); ) {
                Function function = new Function();
                Element e = (Element) rootIter.next();
                String sqlType = e.getName().trim();
                String funcName = e.attributeValue("id").trim();
                String sql = e.getText().trim();
                String resultType = e.attributeValue("resultType").trim();
                function.setSqlType(sqlType);
                function.setFuncName(funcName);
                Object newInstance = null;
                try {
                    newInstance = Class.forName(resultType).newInstance();
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
                function.setResultType(newInstance);
                function.setSql(sql);
                functionList.add(function);
            }
            mapper.setFunctionList(functionList);
            MyMapperRegistry.setConcurrentHashmap(mapper.getInterfaceName(), mapper);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mapper;
    }
}
